//
// Created on 2024/12/6.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#include "FlutterBridge.h"
#include <QDebug>
#include <QString>
#include "FlutterBridgeJsSide.h"
#include "FlutterBridgeQtSide.h"
#include "napi_common.h"

namespace FB {

napi_env FlutterBridge::g_env = nullptr;
napi_ref FlutterBridge::g_ref_napi_obj = nullptr;

napi_status InvokeJsMethod(napi_env env_,
                           napi_ref ref_napi_obj_,
                           const char* methodName,
                           size_t argc,
                           const napi_value* argv) {
  napi_value fn, napi_obj, ret;
  napi_status status;
  status = napi_get_reference_value(env_, ref_napi_obj_, &napi_obj);
  if (status != napi_ok) {
    qCritical()<< "napi_get_reference_value fail ";
    return status;
  }

  status = napi_get_named_property(env_, napi_obj, methodName, &fn);
  if (status != napi_ok) {
    qCritical() << "napi_get_named_property fail " << methodName;
    return status;
  }
  status = napi_call_function(env_, napi_obj, fn, argc, argv, &ret);
  if (status != napi_ok) {
    qCritical() << "napi_call_function fail " << methodName;
    return status;
  }
  return napi_ok;
}


napi_value FlutterBridge::attach(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    FlutterBridge::g_env = env;
    NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
    NAPI_CALL(env, napi_create_reference(env, args[0], 1, &FlutterBridge::g_ref_napi_obj));
    //连接QT信号和槽
    QObject::connect(FlutterBridgeJsSide::instance(), &FlutterBridgeJsSide::sigSendData, 
        FlutterBridgeQtSide::instance(), &FlutterBridgeQtSide::slotReceiveData);
    QObject::connect(FlutterBridgeQtSide::instance(), &FlutterBridgeQtSide::sigSendData,
        FlutterBridgeJsSide::instance(), &FlutterBridgeJsSide::slotReceiveData);   
    return nullptr;
}

napi_value FlutterBridge::notifyWindowCreated(napi_env env, napi_callback_info info) {
    //ArkTS把handle传回给QtWindow
}

/*
    
 */
napi_value FlutterBridge::dispatchMessage(napi_env env, napi_callback_info info) {
    //ArkTS向QT对象发送消息
}

void FlutterBridge::createFlutterWindow() {
    //QT窗口向Flutter发起创建XComponent
    if(FlutterBridge::g_ref_napi_obj == nullptr) {
        qCritical() << "js api object is null";
        return;
    }
    napi_status status = InvokeJsMethod(FlutterBridge::g_env,FlutterBridge::g_ref_napi_obj,
        "createFlutterWindow",0, nullptr);
    if(status != napi_ok) {
        qCritical() << "invoke js object method err code:" << status;
    }
}

void FlutterBridge::handleMessage(const std::string &handler, const std::string &fun, const void* message) {
    //QT向ArkTS发送消息
}

} // namespace FB

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        DECLARE_NAPI_FUNCTION("attach", FB::FlutterBridge::attach),
        DECLARE_NAPI_FUNCTION("notifyWindowCreated", FB::FlutterBridge::notifyWindowCreated),
        DECLARE_NAPI_FUNCTION("dispatchMessage", FB::FlutterBridge::dispatchMessage),
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END
    
static napi_module bridgeModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "flutterbridge",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&bridgeModule); }    